#ifndef UTILS_H_
#define UTILS_H_

#include <pthread.h>
#include "common_defs.h"

// Macros for locking contexts and adding debug prints
#define CONTEXT_LOCK(lock) 	if ( pthread_mutex_lock( & lock ) ) 				\
							{													\
								ERR_PRINT("pthread_mutex_lock() failed!\n");	\
								return ERROR_SYSTEM_CALL;						\
							}													\
							DBG_PRINT("locking the lock\n");

#define CONTEXT_LOCK_NO_RETURN(lock, result) if ( pthread_mutex_lock( & lock ) ) 		\
											 {											\
												ERR_PRINT("pthread_mutex_lock() failed!\n");\
												result =  ERROR_SYSTEM_CALL;				\
											 }												\
											 DBG_PRINT("locking the lock\n");

#define CONTEXT_UNLOCK(lock) 	DBG_PRINT("releasing the lock\n");					\
								if ( pthread_mutex_unlock( & lock ) ) 				\
								{													\
									ERR_PRINT("pthread_mutex_unlock() failed!\n");	\
									return ERROR_SYSTEM_CALL;						\
								}

#define CONTEXT_UNLOCK_NO_RETURN(lock, result) 	DBG_PRINT("releasing the lock\n");				\
												if ( pthread_mutex_unlock( & lock ) ) 			\
												{												\
													ERR_PRINT("pthread_mutex_unlock() failed!\n");\
													result =  ERROR_SYSTEM_CALL;				\
												}



/*
 * wait on the conditional variable that protected by the given mutex
 * assumed the mutex is locked before calling this function.
 * in case unlock_mutex is true the mutex will be unlocked by this function.
 * in case num_waiting is not NULL, the function will advance and decrease it
 * before and after the waiting.
 */

result_t wait_condition_var(pthread_mutex_t *context_lock,
										  pthread_cond_t *cond_var,
										  uint *num_waiting,
										  bool unlock_mutex);


#endif /* UTILS_H_ */
